package cn.ug.operation.service.impl;

import cn.ug.bean.base.SerializeObject;
import cn.ug.bean.type.ResultType;
import cn.ug.config.RedisGlobalLock;
import cn.ug.core.SerializeObjectError;
import cn.ug.core.ensure.Ensure;
import cn.ug.enums.OrderNOPrefixEnum;
import cn.ug.enums.SharePrizeTypeEnum;
import cn.ug.enums.SharePrizeTypeEnum;
import cn.ug.feign.CouponRepertoryService;
import cn.ug.feign.MemberAccountService;
import cn.ug.feign.MemberGroupService;
import cn.ug.feign.MemberUserService;
import cn.ug.member.bean.response.MemberUserBean;
import cn.ug.msg.mq.Msg;
import cn.ug.operation.mapper.ShareJoinMemberMapper;
import cn.ug.operation.mapper.ShareMemberMapper;
import cn.ug.operation.mapper.SharePrizeMapper;
import cn.ug.operation.mapper.entity.*;
import cn.ug.operation.service.DrawPrizeService;
import cn.ug.pay.bean.type.BillGoldTradeType;
import cn.ug.pay.bean.type.TradeType;
import com.alibaba.fastjson.JSONObject;
import org.apache.commons.lang.StringUtils;
import org.springframework.amqp.core.AmqpTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.*;
import java.util.concurrent.ThreadLocalRandom;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

import static cn.ug.config.QueueName.QUEUE_MSG_SEND;
import static cn.ug.util.ConstantUtil.COMMA;

@Service
public class DrawPrizeServiceImpl implements DrawPrizeService {

    @Resource
    private ShareJoinMemberMapper shareJoinMemberMapper;

    @Resource
    private ShareMemberMapper shareMemberMapper;

    @Resource
    private SharePrizeMapper sharePrizeMapper;

    @Autowired
    private MemberUserService memberUserService;

    @Autowired
    private MemberGroupService memberGroupService;

    @Autowired
    private RedisGlobalLock redisGlobalLock;

    @Autowired
    private AmqpTemplate amqpTemplate;

    @Autowired
    private MemberAccountService memberAccountService;

    @Autowired
    private CouponRepertoryService couponRepertoryService;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public SerializeObject draw(String memberId, String orderNo) {
        SerializeObject<MemberUserBean> memberBean = memberUserService.findById(memberId);
        String mobile = "";
        if (memberBean != null && memberBean.getData() != null) {
            MemberUserBean memberUserBean = memberBean.getData();
            mobile = memberUserBean.getMobile();
        } else {
            return new SerializeObject(ResultType.ERROR, "00000005");
        }
        if (StringUtils.isNotBlank(orderNo)){
            //判断订单号是否真实存在
            Map params = OrderNOPrefixEnum.switchString(orderNo);
            String shareMemberId = sharePrizeMapper.queryMemberIdForType(params);
            if (StringUtils.isBlank(shareMemberId)){
                return new SerializeObject(ResultType.ERROR, "25000082");
            }
        }

        String lockKey = "ug:operation:DrawPrizeServiceImpl:draw:" + memberId;
        try {
            if (redisGlobalLock.lock(lockKey, 5000, TimeUnit.MILLISECONDS)) {
                if (StringUtils.isNotBlank(orderNo)) {
                    ShareJoinMemberEntity shareJoinMemberEntity = shareJoinMemberMapper.query(memberId, orderNo);
                    if (shareJoinMemberEntity != null) {
                        return new SerializeObject(ResultType.ERROR, "25000076");
                    }
                }

                //获取配置用户类型  进行用户类型匹配
                List<ShareUserTypeSetting> shareUserTypeSettingList = sharePrizeMapper.queryGroup();
                if (!CollectionUtils.isEmpty(shareUserTypeSettingList)) {
                    List<String> groupIdList = shareUserTypeSettingList.stream().map(o -> String.valueOf(o.getGroupId())).collect(Collectors.toList());
                    String groupIds = String.join(",", groupIdList);
                    SerializeObject object = memberGroupService.getGroupId(memberId, groupIds);
                    if (object == null && object.getData() == null) {
                        return new SerializeObject(ResultType.ERROR, "00000005");
                    }

                    List<SharePrizeEntity> prizes = sharePrizeMapper.queryListByGroupId((Integer) object.getData());
                    if (prizes == null || prizes.size() == 0) {
                        return new SerializeObjectError("00000002");
                    }
                    List<SharePrizeEntity> drawPrizes = new ArrayList<SharePrizeEntity>();
                    for (SharePrizeEntity prize : prizes) {
                        if (prize.getQuantityLimit() == 0) {
                            drawPrizes.add(prize);
                        } else if (prize.getQuantity() > 0) {
                            drawPrizes.add(prize);
                        }
                    }
                    if (drawPrizes == null || drawPrizes.size() == 0) {
                        return new SerializeObjectError("25000065");
                    }
                    SharePrizeEntity prize = getPrize(drawPrizes);
                    ShareMemberEntity shareMemberEntity = new ShareMemberEntity();
                    shareMemberEntity.setStatus(1);
                    shareMemberEntity.setMemberId(memberId);
                    shareMemberEntity.setPrizeId(prize.getId());
                    shareMemberEntity.setOrderNo(orderNo);
                    if (prize.getType() != SharePrizeTypeEnum.UN_PRIZE.getType()) {
                        shareMemberEntity.setRewardsStatus(1);
                    }
                    //shareMemberEntity.setAmount(prize.getAmount());
                    int rows = shareMemberMapper.insert(shareMemberEntity);
                    if (rows > 0) {
                        double amount = 0;
                        if (prize.getType() == SharePrizeTypeEnum.EXPERIENCE_GOLD.getType()) {
                            //体验金
                            SerializeObject bean = memberAccountService.awardGiveOut(memberId, prize.getAmount(), SharePrizeTypeEnum.EXPERIENCE_GOLD.getType());
                            if (bean != null && bean.getCode() == ResultType.NORMAL) {
                                amount = prize.getAmount().doubleValue();
                                Msg msg = new Msg();
                                msg.setMemberId(memberId);
                                msg.setMobile(mobile);
                                msg.setType(cn.ug.msg.bean.status.CommonConstants.MsgType.EXPERIENCE_SHIFT_TO.getIndex());
                                Map<String, String> paramMap = new HashMap<>();
                                paramMap.put("totalGram", String.valueOf(prize.getAmount()));
                                msg.setParamMap(paramMap);
                                amqpTemplate.convertAndSend(QUEUE_MSG_SEND, msg);
                            } else {
                                Ensure.that(0).isLt(1, "00000005");
                            }
                        } else if (prize.getType() == SharePrizeTypeEnum.GOLD_BEAN.getType()) {
                            //金豆发放
                            SerializeObject bean = memberAccountService.awardGiveOut(memberId, prize.getAmount(), SharePrizeTypeEnum.GOLD_BEAN.getType());
                            if (bean != null && bean.getCode() == ResultType.NORMAL) {
                                amount = prize.getAmount().doubleValue();
                                Msg msg = new Msg();
                                msg.setMemberId(memberId);
                                msg.setMobile(mobile);
                                msg.setType(cn.ug.msg.bean.status.CommonConstants.MsgType.EXPERIENCE_SHIFT_TO.getIndex());
                                Map<String, String> paramMap = new HashMap<>();
                                paramMap.put("totalGram", String.valueOf(prize.getAmount()));
                                msg.setParamMap(paramMap);
                                amqpTemplate.convertAndSend(QUEUE_MSG_SEND, msg);
                            } else {
                                Ensure.that(0).isLt(1, "00000005");
                            }
                        } else if (prize.getType() == SharePrizeTypeEnum.KICKBACK.getType()) {
                            //黄金红包
                            if (StringUtils.isBlank(prize.getCouponIds())) {
                                Ensure.that(0).isLt(1, "00000002");
                            }
                            String[] infos = StringUtils.split(prize.getCouponIds(), COMMA);
                            int num = ThreadLocalRandom.current().nextInt(0, infos.length);
                            String couponId = infos[num];
                            SerializeObject bean = couponRepertoryService.giveCoupon(memberId, couponId);
                            if (bean != null && bean.getCode() == ResultType.NORMAL && bean.getData() != null) {
                                amount = Double.parseDouble(bean.getData().toString());
                                Msg msg = new Msg();
                                msg.setMemberId(memberId);
                                msg.setMobile(mobile);
                                msg.setType(cn.ug.msg.bean.status.CommonConstants.MsgType.COUPON_NOTIFY.getIndex());
                                Map<String, String> paramMap = new HashMap<>();
                                paramMap.put("activityName", "砸金蛋");
                                paramMap.put("amount", bean.getData().toString());
                                msg.setParamMap(paramMap);
                                amqpTemplate.convertAndSend(QUEUE_MSG_SEND, msg);
                            } else {
                                Ensure.that(0).isLt(1, "00000005");
                            }
                        } else if (prize.getType() == SharePrizeTypeEnum.INTEREST.getType()) {
                            //回租福利券
                            if (StringUtils.isBlank(prize.getCouponIds())) {
                                Ensure.that(0).isLt(1, "00000002");
                            }
                            String[] infos = StringUtils.split(prize.getCouponIds(), COMMA);
                            int num = ThreadLocalRandom.current().nextInt(0, infos.length);
                            String couponId = infos[num];
                            SerializeObject bean = couponRepertoryService.giveCoupon(memberId, couponId);
                            if (bean != null && bean.getCode() == ResultType.NORMAL && bean.getData() != null) {
                                amount = Double.parseDouble(bean.getData().toString());
                                Msg msg = new Msg();
                                msg.setMemberId(memberId);
                                msg.setMobile(mobile);
                                msg.setType(cn.ug.msg.bean.status.CommonConstants.MsgType.TICKET_NOTIFY.getIndex());
                                Map<String, String> paramMap = new HashMap<>();
                                paramMap.put("activityName", "砸金蛋");
                                paramMap.put("amount", bean.getData().toString());
                                msg.setParamMap(paramMap);
                                amqpTemplate.convertAndSend(QUEUE_MSG_SEND, msg);
                            } else {
                                Ensure.that(0).isLt(1, "00000005");
                            }
                        } else if (prize.getType() == SharePrizeTypeEnum.SHOP_ELECTRONIC_CARD.getType()) {
                            //商城满减券
                            if (StringUtils.isBlank(prize.getCouponIds())) {
                                Ensure.that(0).isLt(1, "00000002");
                            }
                            String[] infos = StringUtils.split(prize.getCouponIds(), COMMA);
                            int num = ThreadLocalRandom.current().nextInt(0, infos.length);
                            String couponId = infos[num];
                            SerializeObject bean = couponRepertoryService.giveCoupon(memberId, couponId);
                            if (bean != null && bean.getCode() == ResultType.NORMAL && bean.getData() != null) {
                                amount = Double.parseDouble(bean.getData().toString());
                                Msg msg = new Msg();
                                msg.setMemberId(memberId);
                                msg.setMobile(mobile);
                                msg.setType(cn.ug.msg.bean.status.CommonConstants.MsgType.TICKET_NOTIFY.getIndex());
                                Map<String, String> paramMap = new HashMap<>();
                                paramMap.put("activityName", "砸金蛋");
                                paramMap.put("amount", bean.getData().toString());
                                msg.setParamMap(paramMap);
                                amqpTemplate.convertAndSend(QUEUE_MSG_SEND, msg);
                            } else {
                                Ensure.that(0).isLt(1, "00000005");
                            }
                        }else if (prize.getType() == SharePrizeTypeEnum.CASH.getType()) {
                            //现金奖励
                            SerializeObject bean = memberAccountService.inviteReturnCash(memberId, prize.getAmount(), TradeType.CASH_REWARDS.getValue());
                            if(bean != null && bean.getCode() == ResultType.NORMAL) {
                                amount = prize.getAmount().doubleValue();
                                Msg msg = new Msg();
                                msg.setMemberId(memberId);
                                msg.setMobile(mobile);
                                msg.setType(cn.ug.msg.bean.status.CommonConstants.MsgType.CASH_REWARDS.getIndex());
                                Map<String, String> paramMap = new HashMap<>();
                                paramMap.put("amount", String.valueOf(prize.getAmount()));
                                msg.setParamMap(paramMap);
                                amqpTemplate.convertAndSend(QUEUE_MSG_SEND, msg);
                            } else {
                                Ensure.that(0).isLt(1,"00000005");
                            }
                        }
                        ShareJoinMemberEntity entity = new ShareJoinMemberEntity();
                        entity.setMemberId(memberId);
                        entity.setOrderNo(orderNo);
                        int row = shareJoinMemberMapper.insert(entity);
                        Ensure.that(row).isLt(1,"00000005");

                        Map map = new HashMap();
                        map.put("amount",amount);
                        map.put("id",shareMemberEntity.getId());
                        int resultRow = shareMemberMapper.update(map);
                        Ensure.that(resultRow).isLt(1,"00000005");

                        JSONObject result = new JSONObject();
                        result.put("prizeName", prize.getName());
                        result.put("amount", amount);
                        result.put("type", prize.getType());
                        result.put("mobile",mobile);
                        return new SerializeObject(ResultType.NORMAL, "00000001",result);
                    }
                }
            }
            return new SerializeObjectError("00000005");
        } finally {
            redisGlobalLock.unlock(lockKey);
        }
    }

    @Override
    public SerializeObject drawRecord(String memberId, String orderNo) {
        Map map = new HashMap();
        map.put("memberId",memberId);
        map.put("orderNo",orderNo);
        ShareMemberEntity shareMemberEntity = shareMemberMapper.queryByOrderNo(map);
        if (shareMemberEntity!=null){
            JSONObject result = new JSONObject();
            result.put("amount", shareMemberEntity.getAmount());
            SharePrizeEntity sharePrizeEntity = sharePrizeMapper.queryById(shareMemberEntity.getPrizeId());
            if (sharePrizeEntity!=null){
                result.put("prizeName", sharePrizeEntity.getName());
                result.put("type", sharePrizeEntity.getType());
            }
            SerializeObject<MemberUserBean> memberBean = memberUserService.findById(memberId);
            if (memberBean != null && memberBean.getData() != null) {
                MemberUserBean memberUserBean = memberBean.getData();
                result.put("mobile",memberUserBean.getMobile());
            }
            return new SerializeObject(ResultType.NORMAL, "00000001",result);
        }

        return new SerializeObject(ResultType.NORMAL, "00000001");
    }

    private SharePrizeEntity getPrize(List<SharePrizeEntity> prizes) {
        //奖品总数
        int size = prizes.size();
        //计算总概率
        BigDecimal sumProbability = BigDecimal.ZERO;
        for (SharePrizeEntity prize : prizes) {
            sumProbability = sumProbability.add(prize.getProbability());
        }

        //计算每个奖品的概率区间
        //例如奖品A概率区间0-0.1  奖品B概率区间 0.1-0.5 奖品C概率区间0.5-1
        //每个奖品的中奖率越大，所占的概率区间就越大
        List<Double> sortAwardProbabilityList = new ArrayList<Double>(size);
        BigDecimal tempSumProbability = BigDecimal.ZERO;
        for (SharePrizeEntity prize : prizes) {
            tempSumProbability = tempSumProbability.add(prize.getProbability());
            sortAwardProbabilityList.add(tempSumProbability.doubleValue() / sumProbability.doubleValue());
        }

        //产生0-1之间的随机数
        //随机数在哪个概率区间内，则是哪个奖品
        double randomDouble = Math.random();
        //加入到概率区间中，排序后，返回的下标则是awardList中中奖的下标
        sortAwardProbabilityList.add(randomDouble);
        Collections.sort(sortAwardProbabilityList);
        int lotteryIndex = sortAwardProbabilityList.indexOf(randomDouble);
        return prizes.get(lotteryIndex);
    }


}
